//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2007
//
// Show dialog for levels selection.
//

# include "StdAfx.h"
# include "Resource.h"
# include "SelectLevels.h"
# include "Map.h"
# include "ListView.h"
# include "Settings.h"
# include "Globals.h"

struct sl_data_t {
	levels_t * pNewLevels;
	bool bRequestGeneralization;
	bool * pbGeneralize;
};

static
INT_PTR CALLBACK _SelectLevelsProc (HWND _hWnd, UINT _uMsg, WPARAM _wParam, LPARAM _lParam) {
	switch (_uMsg) {
		case WM_INITDIALOG: {
			::SetWindowLong (_hWnd, GWL_USERDATA, _lParam);
			sl_data_t * const pData = reinterpret_cast<sl_data_t *> (_lParam);
			levels_t * const pVecNewLevels = pData->pNewLevels;
			assert (pVecNewLevels);

			// Generalize.
			::EnableWindow (::GetDlgItem (_hWnd, IDC_GENERALIZE), pData->bRequestGeneralization);
			if (pData->bRequestGeneralization) {
				const bool bGeneralize = GetSetting ("GeneralizeData", true);
				::CheckDlgButton (_hWnd, IDC_GENERALIZE, bGeneralize ? BST_CHECKED : BST_UNCHECKED);
			}

			// Levels.
			const HWND hList = ::GetDlgItem (_hWnd, IDC_LEVELS);

			ListView_SetExtendedListViewStyleEx (hList, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);

			AddColumn (hList, 1, "Level");

			const size_t cLevels = g_map.Levels.size ();
			if (cLevels > 0)
				for (size_t cLevel = 0; cLevel < cLevels - 1; ++ cLevel) {
					InsertItem (hList, cLevel, cLevel, "Level%d", cLevel);

					if (pVecNewLevels->find (cLevel) != pVecNewLevels->end ())
						ListView_SetCheckState (hList, cLevel, TRUE);
				}

			AutoSizeColumns (hList);

			return TRUE;
		}

		case WM_COMMAND: {
			switch (LOWORD (_wParam)) {
				case IDOK: {
					const HWND hList = ::GetDlgItem (_hWnd, IDC_LEVELS);

					sl_data_t * const pData = reinterpret_cast<sl_data_t *> (::GetWindowLong (_hWnd, GWL_USERDATA));

					// Generalize.
					* pData->pbGeneralize = ::IsDlgButtonChecked (_hWnd, IDC_GENERALIZE) == BST_CHECKED;
					SaveSetting ("GeneralizeData", * pData->pbGeneralize);

					// Levels.
					levels_t * const pVecNewLevels = pData->pNewLevels;
					pVecNewLevels->clear ();
					const size_t cLevels = g_map.Levels.size ();
					if (cLevels > 0) {
						for (size_t cLevel = 0; cLevel < cLevels - 1; ++ cLevel)
							if (ListView_GetCheckState (hList, cLevel) != FALSE)
								pVecNewLevels->insert (cLevel);
					}

					::EndDialog (_hWnd, 0);
					return TRUE;
				}

				case IDCANCEL:
					::EndDialog (_hWnd, 1);
					return TRUE;
			}
		}
	}
	return FALSE;
}

bool SelectLevels (HWND _hWnd, levels_t & _NewLevels) {
	bool b;
	return SelectLevels (_hWnd, false, _NewLevels, b);
}

bool SelectLevels (HWND _hWnd, bool _bRequestGeneralization, levels_t & _NewLevels, bool & _bGeneralize) {
	sl_data_t data = {& _NewLevels, _bRequestGeneralization, & _bGeneralize};

	CCritSec::CLock lock (g_cs);
	return DlgBox (IDD_LEVELS, _hWnd, _SelectLevelsProc, reinterpret_cast<LPARAM> (& data)) == 0;
}

///////////////////////////////////////////////////////////////

static
INT_PTR CALLBACK _SelectLevelProc (HWND _hWnd, UINT _uMsg, WPARAM _wParam, LPARAM _lParam) {
	switch (_uMsg) {
		case WM_INITDIALOG: {
			size_t * const pcLevel = reinterpret_cast<size_t *> (_lParam);
			assert (pcLevel);
			::SetWindowLong (_hWnd, GWL_USERDATA, _lParam);

			char buf [32];

			const HWND hLevels = ::GetDlgItem (_hWnd, IDC_LEVELS);

			const size_t cLevels = g_map.Levels.size ();
			if (cLevels > 0)
				for (size_t cLevel = 0; cLevel < cLevels - 1; ++ cLevel) {
					::sprintf (buf, "Level%d", cLevel);
					::SendMessage (hLevels, CB_INSERTSTRING, cLevel, (LPARAM) buf);
					::SendMessage (hLevels, CB_SETITEMDATA,  cLevel, cLevel);
					if (cLevel == * pcLevel)
						::SendMessage (hLevels, CB_SETCURSEL, cLevel, 0);
				}

			return TRUE;
		}

		case WM_COMMAND: {
			switch (LOWORD (_wParam)) {
				case IDOK: {
					size_t * const pcLevel = reinterpret_cast<size_t *> (::GetWindowLong (_hWnd, GWL_USERDATA));

					const HWND hLevels = ::GetDlgItem (_hWnd, IDC_LEVELS);

					const size_t cLevelsSel = ::SendMessage (hLevels, CB_GETCURSEL, 0, 0);
					if (cLevelsSel != CB_ERR)
						* pcLevel = ::SendMessage (hLevels, CB_GETITEMDATA, cLevelsSel, 0);

					::EndDialog (_hWnd, 0);
					return TRUE;
				}

				case IDCANCEL:
					::EndDialog (_hWnd, 1);
					return TRUE;
			}
		}
	}
	return FALSE;
}

bool SelectLevel (HWND _hWnd, size_t & _cLevel) {
	CCritSec::CLock lock (g_cs);
	return DlgBox (IDD_LEVEL, _hWnd, _SelectLevelProc, reinterpret_cast<LPARAM> (& _cLevel)) == 0;
}